﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using StockLib.Data;

namespace StockLib
{
    public class StockData
    {
        #region 文件目录定义
        private const string DIR_DATA = @"data\";
        private const string DIR_XDR = @"xdr\";
        private const string DIR_NEWS = @"news\";
        private const string DIR_BASE = @"bas\";
        private const string DIR_MONTH = @"mon\";
        private const string DIR_WEEK = @"wek\";
        private const string DIR_DAY = @"day\";
        private const string DIR_MIN5 = @"nmn\";
        private const string DIR_MIN = @"min\";
        private const string DIR_TICK = @"tck\";
        #endregion

        #region 文件后缀定义
        private const string EXT_XDR = @".xdr";
        private const string EXT_NEWS = @".nws";
        private const string EXT_BASE = @".bas";
        private const string EXT_MONTH = @".mnt";
        private const string EXT_WEEK = @".wek";
        private const string EXT_DAY = @".day";
        private const string EXT_MIN5 = @".nmn";
        private const string EXT_MIN = @".min";
        private const string EXT_TICK = @".tck";
        #endregion

        #region 文件路径定义
        private const string FILE_OUTLINE = "outline.dat";
        private const string FILE_CODE = "code.dat";
        //private const string FILE_MINUTE = "minute.dat";
        #endregion

        /// <summary>
        /// 文件存储的根路径
        /// </summary>
        public string RootPath { get; set; }

        /// <summary>
        /// 单例实例
        /// </summary>
        private static StockData _instance = new StockData();

        /// <summary>
        /// 构造函数
        /// </summary>
        private StockData()
        {
            RootPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        }

        /// <summary>
        /// 访问单例
        /// </summary>
        /// <returns></returns>
        public static StockData Instance
        {
            get
            {
                return _instance;
            }
        }

        /// <summary>
        /// 初始化数据库
        /// </summary>
        public virtual void Init()
        {
            if (string.IsNullOrEmpty(RootPath))
                return;

            if (!Directory.Exists(RootPath))
                return;

            foreach (StockMarket market in StockProfile.Markets)
            {
                string[] dirs = new string[] { DIR_XDR, DIR_BASE, DIR_DAY, DIR_MIN5, DIR_MIN, DIR_TICK };
                foreach (string dir in dirs)
                {
                    string path = RootPath + GetMarketDir(market) + dir;
                    if (!Directory.Exists(path))
                        Directory.CreateDirectory(path);
                }
            }
        }

        /// <summary>
        /// 释放数据库
        /// </summary>
        public virtual void Release()
        {
        }

        /// <summary>
        /// 根据市场类型和数据类型，确定文件名称
        /// </summary>
        /// <param name="market">市场类型</param>
        /// <param name="dataType">数据类型</param>
        /// <returns></returns>
        public string GetFileName(StockMarket market, DataType dataType)
        {
            string fileName = null;
            switch (dataType)
            {
                case DataType.Outline:
                    fileName = RootPath + GetMarketDir(market) + FILE_OUTLINE;
                    break;

                case DataType.Code:
                    fileName = RootPath + GetMarketDir(market) + FILE_CODE;
                    break;
            }

            return fileName;
        }

        public string GetFileName(Stock stock, DataType dataType)
        {
            return GetFileName(stock, dataType, KType.None);
        }

        /// <summary>
        /// 根据股票信息和数据类型，确定文件名称
        /// </summary>
        /// <param name="stock">股票信息</param>
        /// <param name="dataType">数据类型</param>
        /// <param name="kType">K线类型</param>
        /// <returns></returns>
        public string GetFileName(Stock stock, DataType dataType, KType kType)
        {
            string fileName = null;

            switch (dataType)
            {
                case DataType.Base:
                    fileName = RootPath + GetMarketDir(stock.Market) + DIR_BASE + stock.Code + EXT_BASE;
                    break;

                case DataType.News:
                    fileName = RootPath + GetMarketDir(stock.Market) + DIR_NEWS + stock.Code + EXT_NEWS;
                    break;

                case DataType.XDR:
                    fileName = RootPath + GetMarketDir(stock.Market) + DIR_XDR + stock.Code + EXT_XDR;
                    break;

                case DataType.K:
                    fileName = RootPath + GetMarketDir(stock.Market);
                    switch (kType)
                    {
                        case KType.Month:
                            fileName += DIR_MONTH + stock.Code + EXT_MONTH;
                            break;

                        case KType.Week:
                            fileName += DIR_WEEK + stock.Code + EXT_WEEK;
                            break;

                        case KType.Day:
                            fileName += DIR_DAY + stock.Code + EXT_DAY;
                            break;

                        case KType.Min5:
                            fileName += DIR_MIN5 + stock.Code + EXT_MIN5;
                            break;

                        case KType.Min:
                            fileName += DIR_MIN + stock.Code + EXT_MIN;
                            break;

                        case KType.Tick:
                            fileName += DIR_TICK + stock.Code + EXT_TICK;
                            break;
                    }
                    break;
            }

            return fileName;
        }

        public void LoadCodeData()
        {
            CodeFileLoader codeLoader = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.CodeLoaderClass))
            {
                codeLoader = new CodeFileLoader();
            }
            else
            {
                codeLoader = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.CodeLoaderClass) as CodeFileLoader;
            }

            codeLoader.Load();
        }

        public void SaveCodeData()
        {
            CodeFileSaver codeSaver = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.CodeSaverClass))
            {
                codeSaver = new CodeFileSaver();
            }
            else
            {
                codeSaver = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.CodeSaverClass) as CodeFileSaver;
            }

            codeSaver.Save();
        }

        public List<KData> LoadKData(Stock stock, KType kType)
        {
            return LoadKData(stock, kType, -1);
        }

        public List<KData> LoadKData(Stock stock, KType kType, int count)
        {
            KFileLoader kLoader = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.KLoaderClass))
            {
                kLoader = new KFileLoader();
            }
            else
            {
                kLoader = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.KLoaderClass) as KFileLoader;
            }

            return kLoader.Load(stock, kType, count);
        }

        public void SaveKData(Stock stock, KType kType, List<KData> kData)
        {
            KFileSaver kSaver = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.KSaverClass))
            {
                kSaver = new KFileSaver();
            }
            else
            {
                kSaver = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.KSaverClass) as KFileSaver;
            }

            kSaver.Save(stock, kType, kData);
        }

        public List<XdrData> LoadXdrData(Stock stock)
        {
            XdrFileLoader xdrLoader = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.XdrLoaderClass))
            {
                xdrLoader = new XdrFileLoader();
            }
            else
            {
                xdrLoader = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.XdrLoaderClass) as XdrFileLoader;
            }

            return xdrLoader.Load(stock);
        }

        public void SaveXdrData(Stock stock, List<XdrData> xdrData)
        {
            XdrFileSaver xdrSaver = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.XdrSaverClass))
            {
                xdrSaver = new XdrFileSaver();
            }
            else
            {
                xdrSaver = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.XdrSaverClass) as XdrFileSaver;
            }

            xdrSaver.Save(stock, xdrData);
        }

        public List<BaseData> LoadBaseData(Stock stock)
        {
            BaseFileLoader baseLoader = null;
            if (string.IsNullOrEmpty(Properties.Settings.Default.BaseLoaderClass))
            {
                baseLoader = new BaseFileLoader();
            }
            else
            {
                baseLoader = Assembly.GetExecutingAssembly().CreateInstance(Properties.Settings.Default.BaseLoaderClass) as BaseFileLoader;
            }

            return baseLoader.Load(stock);
        }


        private string GetMarketDir(StockMarket market)
        {
            return DIR_DATA + market.ToString().ToLower() + Path.DirectorySeparatorChar;
        }
    }
}
